/*
 * StateVariable.java
 *
 * Created on 20 de mayo de 2008, 06:30 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package futbol.forrest.worldModel;


import futbol.forrest.gemetry.Geometry;
import futbol.forrest.gemetry.Line;
import futbol.forrest.gemetry.VecPosition;
import futbol.forrest.utils.Types.*;
import futbol.forrest.utils.*;

/**
 *
 * @author d157743
 */
public class StateVariable {

    static WorldModel model = null;
    static boolean optionDribble = true;    
    
    /** Creates a new instance of StateVariable */
    public StateVariable() {
    }
    
    public static void setWorldModel(WorldModel wm){
        model = wm;
    }
    
    public static void setDribbleOption(boolean option){
        optionDribble = option;
    }
               
    /****** VARIABLE DE ESTADO: esEspacioVacio ******/
    
    boolean isEmptySpace(int nroJugador, DirectionT dir){        
        VecPosition posJugador = model.getPlayerPosition(SetT.SET_TEAMMATES, nroJugador);
        VecPosition posDestino = CalculatePoint.calculateNewPoint(posJugador, dir, Parameters.getParameter(ParaT.PARA_DIST_DRIBBLE_VAREST));
        Line l = Line.makeLineFromTwoPoints(posJugador, posDestino);

        //FILTRO 1: flag de dribble
        if ( !optionDribble ){
//            Log.log(UtiLog, "VariableEstado-esEspacioVacio: FILTRO 1");		
            return false;
        }

        //FILTRO 2: pto destino dentro del campo de juego
        if ( !model.isInField(posDestino, 1) ){
//            Log.log(UtiLog, "VariableEstado-esEspacioVacio: FILTRO 2");		
            return false;
        }

        //FILTRO 3: linea (cono) del dribble despejada. Calculo la cantidad de oponentes que hay en un cono 
        //de centro "posAgente", angulo "angRad" y distancia (posRecepcion - posAgente)
        double angRad = Geometry.Deg2Rad( 30 );
        int cantOpp = model.getCountOpponentInCone(angRad, posJugador, posDestino );

        if ( cantOpp != 0 ){
//            Log.log(UtiLog, "VariableEstado-esEspacioVacio: FILTRO 3");		
            return false;	
        }
        
/* No tenemos esta informacion en la JavaCup
        //FILTRO 4: factibilidad de que la pelota se desplace del origen al destino
        double Vo = wm->getBallSpeed() + (100 * ss->getKickPowerRate() );
        double d = posAgente.getDistanceTo( posDestino );
        double calc = 1 + (d*log(0.94)/Vo);

        if ( calc <= 0 )
        {
                Log.log(UtiLog, "VariableEstado-esEspacioVacio: FILTRO 4");
                return false;
        }
*/
        //FILTRO 5: distancia del oponente mas cercano a posAgente				
        int nroJugadorMasCercano = 0;
        double distJugadorMasCercano = 0;

        model.getOpponentNearness(posJugador, nroJugadorMasCercano, distJugadorMasCercano);

        if ( distJugadorMasCercano < 2.2 ){
//            Log.log(UtiLog, "VariableEstado-esEspacioVacio: FILTRO 5");
            return false;
        }			
        return true;
    }    
    
    
    /****** VARIABLE DE ESTADO: paseNoBloqueado ******/
    
    public static boolean passNotBlocked( int nroPasador, int nroReceptor, DirectionT dirPase){
    
        VecPosition posPasador = model.getPlayerPosition(SetT.SET_TEAMMATES, nroPasador);
        VecPosition posReceptor = model.getPlayerPosition(SetT.SET_TEAMMATES, nroReceptor);

        //Esta consideracion es para cuando utilizamos los grafos de coordinacion....en otro caso, la direccion del pase es siempre al centro
        //por lo que no influye en el calculo del pto a donde se realiza el pase (es donde se encuentra el receptor)
        double distPase = getDistPass( posPasador, posReceptor);	

        //Se calula el pto de recepcion del pase
        VecPosition posDestino = CalculatePoint.calculateNewPoint(posReceptor, dirPase, distPase);
        Line l = Line.makeLineFromTwoPoints( posPasador, posDestino);

        //FILTRO 1: el pase tiene que estar en el rango permitido
        if (!isPassInRange( posPasador, posDestino)){
//            Log.log(UtiLog, "VariableEstado-paseNoBloqueado: FILTRO 1");		
            return false;
        }


        //FILTRO 3: pto destino dentro del campo de juego
        if ( !model.isInField(posDestino, 1) ){
//            Log.log(UtiLog, "VariableEstado-paseNoBloqueado: FILTRO 3");		
            return false;
        }

        //FILTRO 4: linea (cono) del dribble despejada. 
        double angRad = Geometry.Deg2Rad( 27 );	

        VecPosition posGoal = model.getCenterPosGoalOpponents();
        double distArcoOpon =  posPasador.getDistanceTo(posGoal);

        if ( distArcoOpon < 20 )
            angRad = Geometry.Deg2Rad( 26 );		
        else
            angRad = Geometry.Deg2Rad( 28 );	


        int cantOpp = model.getCountOpponentInCone(angRad, posPasador, posDestino);

        if ( cantOpp != 0 ){
//            Log.log(UtiLog, "VariableEstado-paseNoBloqueado: FILTRO 4");		
            return false;	
        }

/* no tenemos esta informacion en la javaCup
        //FILTRO 5: factibilidad de que la pelota se desplace del origen al destino
        double Vo = wm->getBallSpeed() + (100 * ss->getKickPowerRate() );
        double d = posPasador.getDistanceTo( posDestino );
        double calc = 1 + (d*log(0.94)/Vo);

        if ( calc <= 0 )
        {
                Log.log(UtiLog, "VariableEstado-paseNoBloqueado: FILTRO 5");
                return false;
        }
*/        
        //FILTRO 6: distancia del oponente mas cercano a posDestino				
        int nroJugadorMasCercano = 0;
        double distJugadorMasCercano = 0;
        
        model.getOpponentNearness(posDestino, nroJugadorMasCercano, distJugadorMasCercano);        

        if ( distJugadorMasCercano < 1.0 ){
//            Log.log(UtiLog, "VariableEstado-paseNoBloqueado: FILTRO 6");
            return false;
        }

//        Log.log(UtiLog, "VariableEstado-paseNoBloqueado: PASE DESPEJADO");					
        return true;	
    }	  
        
    /****** VARIABLE DE ESTADO: paseEnRango ******/

    public static boolean isPassInRange(VecPosition posPasador, VecPosition posReceptor){         
        VecPosition posGoal = model.getCenterPosGoalOpponents();
        double distArcoOpon =  posReceptor.getDistanceTo( posGoal );
        double distAgentes = posPasador.getDistanceTo( posReceptor );	
        double mtsAtras;

        //Si la distancia entre los jugadores es mayor a MAX_DIST_PASE devuelvo false
        if ( distAgentes > Parameters.getParameter(ParaT.PARA_MAX_DIST_PASE) ) 
            return false;

        //Dependiendo de la posicion del Receptor son los mts hacia atras que habilito el pase
        if ( distArcoOpon < 25.0 )
            mtsAtras = 7.5;
        else if ( distArcoOpon < 60 )
            mtsAtras = 7.5;	
        else if  ( distArcoOpon < 65 )
            mtsAtras = 2.5;
        else
            mtsAtras = 2.5;

        if (posReceptor.getX() >= posPasador.getX() - mtsAtras )
            return true;
        else
            return false;
     }   
        
    /****** VARIABLE DE ESTADO: getMaxDistPaseAtras ********/
    
    public static double getMaxDistPassBack(){
        return 7.5;
    }

    /****** VARIABLE DE ESTADO: tiroNoBloqueado ******/

    public static boolean shootNotBlocked(VecPosition posPateador, VecPosition posDestino){
        return true;
    }		 

    /****** VARIABLE DE ESTADO: esPosicionDeAtaque ******/

    public static boolean isAttackPosition( int nroJugador){
        VecPosition posJugador = model.getPlayerPosition(SetT.SET_TEAMMATES, nroJugador);
        return isAttackPosition(posJugador);
    }

    public static boolean isAttackPosition(VecPosition posJugador){
        VecPosition posGoal = model.getCenterPosGoalOpponents();
        double distArcoOpon =  posJugador.getDistanceTo(posGoal);
        
        if (distArcoOpon < Parameters.getParameter(ParaT.PARA_ATTACK_ZONE))
                return true;
        else
                return false;
    }    
    
    /****** VARIABLE DE ESTADO: esPosicionDribbleEastWest ******/

    public static boolean isPositionDribbleEastWest(VecPosition posJugador){
        VecPosition posGoal = model.getCenterPosGoalOpponents();
        double distArcoOpon =  posJugador.getDistanceTo(posGoal);

        if (distArcoOpon < 35)
            return true;
        else
            return false;
    }
    
    public static double getDistPass(VecPosition posPasador, VecPosition posReceptor){   
        double 	adyacente = posPasador.getDistanceTo(posReceptor);
        double 	distPase;		

        double	tangente = Geometry.tanDeg(14.0); 
        double	topeDistPase = 3.5; 

        if ( adyacente < 5.0 )
            distPase = 0;
        else{
            distPase = tangente*adyacente;		
            if ( distPase > topeDistPase )
                distPase = topeDistPase;
        }

        return distPase;
    }        
}
